/**
 * 
 */
package org.mspring.mlog.api.spider;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.log4j.Logger;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.mspring.mlog.api.spider.crawler.Crawler;
import org.mspring.mlog.api.spider.entity.SpiderRule;
import org.mspring.mlog.api.spider.handler.ContentHandler;
import org.mspring.mlog.api.spider.handler.TitleHandler;

/**
 * @author Gao Youbo
 * @since 2013-3-8
 * @description
 * @TODO
 */
public class Spider {
    private static final Logger log = Logger.getLogger(Spider.class);
    private Crawler crawler;
    private Map<String, TitleHandler> titleHandlers;
    private Map<String, ContentHandler> contentHandlers;

    public Crawler getCrawler() {
        return crawler;
    }

    public void setCrawler(Crawler crawler) {
        this.crawler = crawler;
    }

    public Map<String, TitleHandler> getTitleHandlers() {
        return titleHandlers;
    }

    public Map<String, ContentHandler> getContentHandlers() {
        return contentHandlers;
    }

    private Map<String, Object> context;

    public Map<String, Object> getContext() {
        return context;
    }

    public void setContext(Map<String, Object> context) {
        this.context = context;
    }

    public void addContextValue(String key, Object value) {
        if (context == null) {
            context = new HashMap<String, Object>();
        }
        context.put(key, value);
    }

    public Object getContextValue(String key) {
        if (context == null) {
            return null;
        }
        return context.get(key);
    }

    /**
     * 
     */
    public Spider() {
        // TODO Auto-generated constructor stub
    }

    public Spider(Crawler crawler) {
        super();
        this.crawler = crawler;
    }

    public void addContentHandler(String key, ContentHandler contentHandler) {
        if (this.contentHandlers == null) {
            this.contentHandlers = new HashMap<String, ContentHandler>();
        }
        contentHandlers.put(key, contentHandler);
    }

    public void addTitleHandler(String key, TitleHandler titleHandler) {
        if (this.titleHandlers == null) {
            this.titleHandlers = new HashMap<String, TitleHandler>();
        }
        titleHandlers.put(key, titleHandler);
    }

    public List<String> getUrls(Document doc, SpiderRule rule) {
        if (crawler == null) {
            log.warn("Crawler is null");
            return null;
        }
        List<String> urls = crawler.getUrls(doc, rule);
        return urls;
    }

    public Element getTitle(Document doc, SpiderRule rule) {
        if (crawler == null) {
            log.warn("Crawler is null");
            return null;
        }
        Element title = crawler.getTitle(doc, rule);
        if (titleHandlers != null && titleHandlers.size() > 0) {
            for (Map.Entry<String, TitleHandler> entry : titleHandlers.entrySet()) {
                log.debug("title handler... key = " + entry.getKey());
                try {
                    title = entry.getValue().handle(title);
                } catch (Exception e) {
                    // TODO: handle exception
                    continue;
                }
            }
        }
        return title;
    }

    public Element getContent(Document doc, SpiderRule rule) {
        if (crawler == null) {
            log.warn("Crawler is null");
            return null;
        }
        Element content = crawler.getContent(doc, rule);
        if (contentHandlers != null && contentHandlers.size() > 0) {
            for (Map.Entry<String, ContentHandler> entry : contentHandlers.entrySet()) {
                log.debug("content handler... key = " + entry.getKey());
                try {
                    content = entry.getValue().handle(content);
                } catch (Exception e) {
                    // TODO: handle exception
                    continue;
                }
            }
        }
        return content;
    }

    /**
     * 设置ContentHandler处理过程变量
     * 
     * @param handlerKey
     * @param contextKey
     * @param contextValue
     */
    public void addContentHandlerContext(String handlerKey, String contextKey, Object contextValue) {
        if (contentHandlers == null) {
            return;
        }
        ContentHandler contentHandler = contentHandlers.get(handlerKey);
        if (contentHandler == null) {
            return;
        }
        contentHandler.addContextValue(contextKey, contextValue);
    }

    /**
     * 获取ContentHandler处理过程变量
     * 
     * @param handlerKey
     * @param contextKey
     * @return
     */
    public Object getContentHandlerContext(String handlerKey, String contextKey) {
        if (contentHandlers == null) {
            return null;
        }
        ContentHandler contentHandler = contentHandlers.get(handlerKey);
        if (contentHandler == null) {
            return null;
        }
        return contentHandler.getContextValue(contextKey);
    }

}
